{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "12058891",
   "metadata": {},
   "source": [
    "\n",
    "# 基于修改后的 MindQuantum 0.5.0 采用变分算法重构半导体双量子点单-三重态量子 CZ 门"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11259757",
   "metadata": {},
   "source": [
    "# 采用自定义的 MQLayer abs 来实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "355416b3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error_min: 0.7284220873912217 error_now: 0.7284220873912217 train_num: 0\n",
      "error_min: 0.4659930631862742 error_now: 0.5032378009903851 train_num: 50\n",
      "error_min: 0.32920229189059214 error_now: 0.41045665838040957 train_num: 100\n",
      "error_min: 0.14859649090207938 error_now: 0.14859649090207938 train_num: 150\n",
      "error_min: 0.12639008657954098 error_now: 0.19375665229527717 train_num: 200\n",
      "error_min: 0.050129373919741815 error_now: 0.050129373919741815 train_num: 250\n",
      "error_min: 0.041020447415039296 error_now: 0.047751516466245536 train_num: 300\n",
      "error_min: 0.03726347991238632 error_now: 0.04683054248060836 train_num: 350\n",
      "error_min: 0.02930082262765077 error_now: 0.030186070786646146 train_num: 400\n",
      "error_min: 0.022283901801077755 error_now: 0.02265701744097559 train_num: 450\n",
      "error_min: 0.02117732176026199 error_now: 0.022497318745653194 train_num: 500\n",
      "error_min: 0.018884560299317288 error_now: 0.024477606917692962 train_num: 550\n",
      "error_min: 0.018884560299317288 error_now: 0.028055087762377195 train_num: 600\n",
      "error_min: 0.018884560299317288 error_now: 0.044716062870351014 train_num: 650\n",
      "error_min: 0.018884560299317288 error_now: 0.05334772225821727 train_num: 700\n",
      "error_min: 0.018884560299317288 error_now: 0.03143433303739973 train_num: 750\n",
      "error_min: 0.0186836052040813 error_now: 0.0186836052040813 train_num: 800\n",
      "error_min: 0.01494267525354942 error_now: 0.017952033148770474 train_num: 850\n",
      "error_min: 0.012973258557989809 error_now: 0.01395139350591379 train_num: 900\n",
      "error_min: 0.005227822750404121 error_now: 0.005472277798355019 train_num: 950\n",
      "error_min: 0.0005501161435323976 error_now: 0.0006094013213763239 train_num: 1000\n",
      "error_min: 0.00011255040322666332 error_now: 0.00019101628881457167 train_num: 1050\n",
      "error_min: 0.00011167871944839369 error_now: 0.00014088419926194806 train_num: 1100\n",
      "error_min: 2.3074306926829102e-05 error_now: 2.3074306926829102e-05 train_num: 1150\n",
      "\n",
      "error_min: 9.971979081924154e-06 train_num: 1162\n",
      "params_tem:\n",
      " [1.5472503  1.4179231  1.540713   1.9724044  1.9253408  1.3879265\n",
      " 0.8130467  0.76446086 1.2703444  1.8553745  1.0291328  1.2492974\n",
      " 0.7880994  0.3026381  0.31203356 0.30834132 0.9533752  1.3802187\n",
      " 1.270656   0.5646567  0.94619316 0.97377133 1.9658349  0.83277696\n",
      " 1.0190777  0.90001523 0.26008993 0.16526282 0.22249524 1.1596956\n",
      " 1.5285202  0.4919534  0.01645389 0.02608137 0.6504683  0.31325826\n",
      " 0.4486266  0.8677286  1.3571227  1.4995408  1.1248059  0.5996333\n",
      " 0.32797617 0.54987127]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import sys\n",
    "from numpy import kron\n",
    "from mindquantum import *\n",
    "from scipy.linalg import expm\n",
    "import mindspore as ms\n",
    "from mindspore import ops, Tensor\n",
    "ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target=\"CPU\")\n",
    "from mindspore.nn import Adam, TrainOneStepCell\n",
    "from mindspore.common.parameter import Parameter\n",
    "from mindspore.common.initializer import initializer  \n",
    "ms.set_seed(1)\n",
    "np.random.seed(1)\n",
    "\n",
    "train_x = np.load('./src/cz_train_x.npy', allow_pickle=True)\n",
    "eval_x = np.load('./src/cz_eval_x.npy', allow_pickle=True)\n",
    "train_y = np.load('./src/cz_train_y.npy', allow_pickle=True)\n",
    "eval_y = np.load('./src/cz_eval_y.npy', allow_pickle=True)\n",
    "\n",
    "s_x = X.matrix()\n",
    "s_z = Z.matrix()\n",
    "one = I.matrix()\n",
    "dt = np.pi/10\n",
    "\n",
    "def _matrix_0(coeff):\n",
    "    return expm(-1j*(coeff*s_z+s_x)*dt)\n",
    "\n",
    "def _diff_matrix_0(coeff):\n",
    "    return -1j*_matrix_0(coeff)@(s_z*dt)\n",
    "\n",
    "def _matrix_c_0(coeff):\n",
    "    return expm(-1j*(coeff*kron(s_z, one) + kron(one, s_z) + kron(s_x, one) + kron(one, s_x) + coeff*kron(s_z-one, s_z-one))*5*dt)\n",
    "\n",
    "def _diff_matrix_c_0(coeff):\n",
    "    return -1j*_matrix_c_0(coeff)@((kron(s_z, one) + kron(s_z-one, s_z-one)) * 5*dt)\n",
    "\n",
    "def _matrix_c_1(coeff):\n",
    "    return expm(-1j*(kron(s_z, one) + coeff*kron(one, s_z) + kron(s_x, one) + kron(one, s_x) + coeff*kron(s_z-one, s_z-one))*5*dt)\n",
    "\n",
    "def _diff_matrix_c_1(coeff):\n",
    "    return -1j*_matrix_c_1(coeff)@((kron(one, s_z) + kron(s_z-one, s_z-one)) *  5*dt)\n",
    "\n",
    "gate_0 = gene_univ_parameterized_gate('gete_0', _matrix_0, _diff_matrix_0)\n",
    "gate_c_0 = gene_univ_parameterized_gate('gete_c_0', _matrix_c_0, _diff_matrix_c_0)\n",
    "gate_c_1 = gene_univ_parameterized_gate('gete_c_1', _matrix_c_1, _diff_matrix_c_1)\n",
    "\n",
    "circ = Circuit()\n",
    "\n",
    "circ += gate_0('00').on(0)\n",
    "circ += gate_0('01').on(0)\n",
    "circ += gate_0('02').on(0)\n",
    "circ += gate_0('03').on(0)\n",
    "circ += gate_0('04').on(0)\n",
    "circ += gate_0('05').on(0)\n",
    "circ += gate_0('06').on(0)\n",
    "circ += gate_0('07').on(0)\n",
    "circ += gate_0('08').on(0)\n",
    "circ += gate_0('09').on(0)\n",
    "\n",
    "circ += gate_0('10').on(1)\n",
    "circ += gate_0('11').on(1)\n",
    "circ += gate_0('12').on(1)\n",
    "circ += gate_0('13').on(1)\n",
    "circ += gate_0('14').on(1)\n",
    "circ += gate_0('15').on(1)\n",
    "circ += gate_0('16').on(1)\n",
    "circ += gate_0('17').on(1)\n",
    "circ += gate_0('18').on(1)\n",
    "circ += gate_0('19').on(1)\n",
    "\n",
    "circ += gate_c_0('0').on([1,0])\n",
    "circ += gate_c_0('1').on([1,0])\n",
    "circ += gate_c_1('2').on([1,0])\n",
    "circ += gate_c_1('3').on([1,0])\n",
    "\n",
    "circ += gate_0('010').on(0)\n",
    "circ += gate_0('011').on(0)\n",
    "circ += gate_0('012').on(0)\n",
    "circ += gate_0('013').on(0)\n",
    "circ += gate_0('014').on(0)\n",
    "circ += gate_0('015').on(0)\n",
    "circ += gate_0('016').on(0)\n",
    "circ += gate_0('017').on(0)\n",
    "circ += gate_0('018').on(0)\n",
    "circ += gate_0('019').on(0)\n",
    "\n",
    "circ += gate_0('110').on(1)\n",
    "circ += gate_0('111').on(1)\n",
    "circ += gate_0('112').on(1)\n",
    "circ += gate_0('113').on(1)\n",
    "circ += gate_0('114').on(1)\n",
    "circ += gate_0('115').on(1)\n",
    "circ += gate_0('116').on(1)\n",
    "circ += gate_0('117').on(1)\n",
    "circ += gate_0('118').on(1)\n",
    "circ += gate_0('119').on(1)\n",
    "\n",
    "ham = Hamiltonian(QubitOperator('')) \n",
    "sim = Simulator('projectq', circ.n_qubits)\n",
    "sim_left = Simulator('projectq',circ.n_qubits)\n",
    "grad_ops = sim.get_expectation_with_grad(ham,\n",
    "                                         circ,\n",
    "                                         circ_left=Circuit(),\n",
    "                                         simulator_left=sim_left,\n",
    "                                         ansatz_params_name=circ.params_name)\n",
    "lr = 0.02\n",
    "Quantum_net = MQLayer(grad_ops)\n",
    "opti = Adam(Quantum_net.trainable_params(), learning_rate=lr)  \n",
    "net = TrainOneStepCell(Quantum_net, opti)\n",
    "error_min = 1\n",
    "\n",
    "for j in range(len(train_x)):\n",
    "    net(Tensor(train_x[j]), Tensor(train_y[j]))\n",
    "    params = abs(Quantum_net.weight.asnumpy())\n",
    "    final_state = []\n",
    "    for k in range(100): # 100 个测试点\n",
    "        sim.reset()\n",
    "        sim.set_qs(eval_x[k])\n",
    "        sim.apply_circuit(circ, params)\n",
    "        final_state.append(sim.get_qs())\n",
    "    error = 1-np.real(np.min([np.abs(np.vdot(bra, ket)) for bra, ket in zip(np.array(final_state), eval_y)]))\n",
    "    if error < error_min:\n",
    "        error_min = error\n",
    "        params_tem = params\n",
    "        j_tem = j\n",
    "    if j % 50 == 0:\n",
    "        print('error_min:', error_min, 'error_now:', error, 'train_num:', j)\n",
    "    if error_min < 1e-5:\n",
    "        break\n",
    "        \n",
    "print('\\nerror_min:', error_min, 'train_num:', j_tem)\n",
    "print('params_tem:\\n', params_tem)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
